package ioc

import (
	"errors"
	"fmt"
)

// CreateProxy 创建代理逻辑
type CreateProxy[T any] func(target T) T

// AopByName 为名称为name的组件创建Aop，注意T必须是接口类型，需在InjectComponents之前调用
// @Param name 组件名称
// @Param iaop 代理逻辑
func AopByName[T any](name string, creareProxy CreateProxy[T]) {
	aopFn := func(c IContainer, cptr *Component) bool {
		if name == cptr.Name() {
			if v, ok := cptr.Value.(T); ok {
				cptr.Value = creareProxy(v)
			} else {
				panic(errors.New(fmt.Sprintf("Component with name [%s] does not match type  T!!", name)))
			}
		}

		return true
	}

	AddAfterComponentRegister(aopFn)
}

// AopByType 为所有T类型组件加aop,注意T必须是接口类型，需在InjectComponents之前调用
func AopByType[T any](creareProxy CreateProxy[T]) {
	aopFn := func(c IContainer, cptr *Component) bool {
		if v, ok := cptr.Value.(T); ok {
			cptr.Value = creareProxy(v)
		}
		return true
	}

	AddAfterComponentRegister(aopFn)
}
